<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能IPTV播放器</title>
    <link href="https://vjs.zencdn.net/7.20.3/video-js.min.css" rel="stylesheet">
    <script src="https://vjs.zencdn.net/7.20.3/video.min.js"></script>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;700&display=swap" rel="stylesheet">
    <style>
        :root {
            --primary-color: #2c3e50;
            --secondary-color: #34495e;
            --accent-color: #3498db;
            --background-color: #ecf0f1;
            --text-color: #2c3e50;
            --hover-color: #e74c3c;
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: 'Noto Sans SC', sans-serif;
            background-color: var(--background-color);
            color: var(--text-color);
            line-height: 1.6;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }

        header {
            background-color: var(--primary-color);
            color: white;
            text-align: center;
            padding: 20px 0;
            margin-bottom: 30px;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
        }

        h1 {
            font-size: 2.5em;
            font-weight: 700;
            letter-spacing: 2px;
        }

        .content {
            display: flex;
            gap: 30px;
            background-color: white;
            border-radius: 15px;
            overflow: hidden;
            box-shadow: 0 10px 20px rgba(0,0,0,0.1);
        }

        #channel-list {
            flex: 0 0 300px;
            height: calc(100vh - 200px);
            overflow-y: auto;
            background-color: var(--secondary-color);
            padding: 20px;
            scrollbar-width: thin;
            scrollbar-color: var(--accent-color) var(--secondary-color);
        }

        #channel-list::-webkit-scrollbar {
            width: 8px;
        }

        #channel-list::-webkit-scrollbar-track {
            background: var(--secondary-color);
        }

        #channel-list::-webkit-scrollbar-thumb {
            background-color: var(--accent-color);
            border-radius: 20px;
        }

        #channel-list button {
            display: block;
            width: 100%;
            padding: 15px;
            border: none;
            background-color: transparent;
            color: white;
            text-align: left;
            cursor: pointer;
            transition: all 0.3s ease;
            border-radius: 8px;
            margin-bottom: 10px;
        }

        #channel-list button:hover, #channel-list button.active {
            background-color: var(--accent-color);
            transform: translateX(5px);
        }

        #player-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }

        #video-wrapper {
            width: 100%;
            max-width: 1080px;
            position: relative;
            padding-top: 56.25%; /* 16:9 Aspect Ratio */
        }

        .video-js {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
        }

        .channel-item {
            display: flex;
            align-items: center;
        }

        .channel-icon {
            width: 40px;
            height: 40px;
            margin-right: 15px;
            object-fit: contain;
            border-radius: 50%;
            background-color: white;
            padding: 5px;
            transition: transform 0.3s ease;
        }

        #channel-list button:hover .channel-icon {
            transform: scale(1.1);
        }

        .channel-info {
            display: flex;
            flex-direction: column;
            flex-grow: 1;
            overflow: hidden;
        }

        .channel-name {
            font-weight: bold;
            margin-bottom: 5px;
            font-size: 1em;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .channel-description {
            font-size: 0.8em;
            opacity: 0.8;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        #controls {
            display: none;
            justify-content: center;
            gap: 20px;
            margin-top: 20px;
        }

        #controls button {
            padding: 10px 20px;
            font-size: 1em;
            background-color: var(--accent-color);
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        #controls button:hover {
            background-color: var(--hover-color);
        }

        #keyboard-info {
            text-align: center;
            margin-top: 20px;
            color: var(--text-color);
            font-size: 0.9em;
            background-color: rgba(255, 255, 255, 0.8);
            padding: 10px;
            border-radius: 5px;
        }

        @media (max-width: 968px) {
            .content {
                flex-direction: column;
            }

            #channel-list, #player-container {
                width: 100%;
            }

            #channel-list {
                height: 300px;
                flex: none;
            }

            #controls {
                display: flex;
            }

            #keyboard-info {
                display: none;
            }
        }
    </style>
</head>
<body>
    <header>
        <h1>智能IPTV播放器</h1>
    </header>
    <div class="container">
        <div class="content">
            <div id="channel-list"></div>
            <div id="player-container">
                <div id="video-wrapper">
                    <video-js id="my-video" class="video-js vjs-big-play-centered" controls preload="auto" data-setup='{"techOrder": ["html5"]}'>
                        <p class="vjs-no-js">
                            To view this video please enable JavaScript, and consider upgrading to a web browser that
                            <a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
                        </p>
                    </video-js>
                </div>
            </div>
        </div>
        <div id="controls">
            <button id="prev-channel">上一个频道</button>
            <button id="next-channel">下一个频道</button>
        </div>
        <div id="keyboard-info">
            使用键盘上下方向键可以切换频道，回车键确认选择
        </div>
    </div>

    <script>
        // JavaScript 代码保持不变
        const playlistUrl = 'https://raw.githubusercontent.com/hujingguang/ChinaIPTV/main/cnTV_AutoUpdate.m3u8';
        const channelList = document.getElementById('channel-list');
        const player = videojs('my-video', {
            html5: {
                hls: {
                    overrideNative: true
                }
            }
        });

        let currentChannelIndex = -1;
        let channels = [];

        function isValidIpv4Url(string) {
            try {
                const url = new URL(string);
                return !string.includes('[') && !string.includes(']');
            } catch (_) {
                return false;
            }
        }

        function parseM3ULine(line) {
            if (line.startsWith('http://') || line.startsWith('https://')) {
                return line.trim();
            }
            return null;
        }

        function extractTvgInfo(extinf) {
            const logoMatch = extinf.match(/tvg-logo="([^"]+)"/);
            const nameMatch = extinf.match(/tvg-name="([^"]+)"/);
            return {
                logo: logoMatch ? logoMatch[1] : null,
                name: nameMatch ? nameMatch[1] : null
            };
        }

        function playChannel(index) {
            if (index >= 0 && index < channels.length) {
                const channel = channels[index];
                player.src({
                    type: 'application/x-mpegURL',
                    src: channel.url
                });
                player.play();
                channelList.querySelectorAll('button').forEach(btn => btn.classList.remove('active'));
                channelList.children[index].classList.add('active');
                currentChannelIndex = index;
                channelList.children[index].scrollIntoView({ behavior: 'smooth', block: 'nearest' });
            }
        }

        fetch(playlistUrl)
            .then(response => response.text())
            .then(data => {
                const lines = data.split('\n');
                for (let i = 0; i < lines.length; i++) {
                    if (lines[i].startsWith('#EXTINF')) {
                        const tvgInfo = extractTvgInfo(lines[i]);
                        const title = lines[i].split(',')[1];
                        const url = parseM3ULine(lines[i+1]);
                        if (url && isValidIpv4Url(url)) {
                            channels.push({ title, url, tvgInfo });
                            const button = document.createElement('button');
                            const channelItem = document.createElement('div');
                            channelItem.className = 'channel-item';

                            if (tvgInfo.logo) {
                                const img = document.createElement('img');
                                img.src = tvgInfo.logo;
                                img.className = 'channel-icon';
                                img.onerror = function() { this.style.display = 'none'; };
                                channelItem.appendChild(img);
                            }

                            const infoDiv = document.createElement('div');
                            infoDiv.className = 'channel-info';

                            const nameSpan = document.createElement('span');
                            nameSpan.className = 'channel-name';
                            nameSpan.textContent = tvgInfo.name || title;
                            infoDiv.appendChild(nameSpan);

                            if (tvgInfo.name && tvgInfo.name !== title) {
                                const descSpan = document.createElement('span');
                                descSpan.className = 'channel-description';
                                descSpan.textContent = title;
                                infoDiv.appendChild(descSpan);
                            }

                            channelItem.appendChild(infoDiv);
                            button.appendChild(channelItem);
                            channelList.appendChild(button);
                        }
                    }
                }
                if (channels.length > 0) {
                    playChannel(0);
                }
                // 修复鼠标点击bug
                channelList.querySelectorAll('button').forEach((button, index) => {
                    button.onclick = function() {
                        playChannel(index);
                    };
                });
            })
            .catch(error => console.error('Error:', error));

        document.addEventListener('keydown', function(e) {
            if (e.key === 'ArrowUp') {
                playChannel(Math.max(0, currentChannelIndex - 1));
            } else if (e.key === 'ArrowDown') {
                playChannel(Math.min(channels.length - 1, currentChannelIndex + 1));
            } else if (e.key === 'Enter') {
                playChannel(currentChannelIndex);
            }
        });

        document.getElementById('prev-channel').addEventListener('click', function() {
            playChannel(Math.max(0, currentChannelIndex - 1));
        });

        document.getElementById('next-channel').addEventListener('click', function() {
            playChannel(Math.min(channels.length - 1, currentChannelIndex + 1));
        });

        // 添加触摸屏滑动切换频道功能
        let touchStartX = 0;
        let touchEndX = 0;

        document.addEventListener('touchstart', function(e) {
            touchStartX = e.changedTouches[0].screenX;
        }, false);

        document.addEventListener('touchend', function(e) {
            touchEndX = e.changedTouches[0].screenX;
            handleSwipe();
        }, false);

        function handleSwipe() {
            if (touchEndX < touchStartX) {
                // 向左滑动，下一个频道
                playChannel(Math.min(channels.length - 1, currentChannelIndex + 1));
            }
            if (touchEndX > touchStartX) {
                // 向右滑动，上一个频道
                playChannel(Math.max(0, currentChannelIndex - 1));
            }
        }
    </script>
</body>
</html>